package uncharteddal

import (
	"encoding/json"
	"fmt"

	"public.com/goutil/debugUtil"
	"public.com/goutil/logUtil"

	"7qule.com/sd3/CrossServer/src/common/onlinelog"
	"7qule.com/sd3/CrossServer/src/dal"
	"7qule.com/sd3/CrossServer/src/dal/playerdal"
	"7qule.com/sd3/CrossServer/src/model/redisKey"
	"7qule.com/sd3/CrossServer/src/model/uncharted"
	"github.com/garyburd/redigo/redis"
)

// 获取所有玩家的信息，以便进行排行统计
// 返回值：
// 积分排行数据
// 是否存在数据
// 错误对象
func GetAllPlayerInfo() (rankItemList []*uncharted.RankItem, exists bool, err error) {
	var keys []string
	if keys, exists, err = playerdal.GetAllPlayerKey(); err != nil || !exists {
		return
	}

	conn := dal.GetRedisPool().GetConnection()
	defer conn.Close()

	// 遍历所有的Key
	for _, key := range keys {
		var id string = redisKey.GetPlayerId(key)
		var name string
		var headImageId int
		var pvpInterLv int
		var serverGroupId int
		var serverId int
		var zone string
		var guildName string
		var fashionModelId int
		var score int
		var tempScore int
		var vip int
		var lv int
		var diyHeadPortraitId string
		var scoreChangeTime int64
		var mapId int8
		var star int

		reply, err := conn.Do("HMGET",
			key,
			redisKey.Player_Name,
			redisKey.Player_HeadImageId,
			redisKey.Player_PVPInterLv,
			redisKey.Player_ServerGroupId,
			redisKey.Player_ServerId,
			redisKey.Player_Zone,
			redisKey.Player_GuildName,
			redisKey.Player_FashionModelId,
			redisKey.Uncharted_Score,
			redisKey.Uncharted_TempTerritoryScore,
			redisKey.Player_Vip,
			redisKey.Player_Lv,
			redisKey.Player_DiyHeadPortraitId,
			redisKey.Uncharted_ScoreChangeTime,
			redisKey.Uncharted_MapId,
			redisKey.Uncharted_Star,
		)

		if err != nil {
			logUtil.Log(fmt.Sprintf("uncharted.GetAllPlayerInfo 从Redis中获取玩家信息出错1，错误信息为：%s", err), logUtil.Error, true)
			continue
		}

		values, err := redis.Values(reply, err)
		if err != nil {
			logUtil.Log(fmt.Sprintf("uncharted.GetAllPlayerInfo 从Redis中获取玩家信息出错2，错误信息为：%s", err), logUtil.Error, true)
			continue
		}

		if _, err := redis.Scan(values, &name, &headImageId, &pvpInterLv, &serverGroupId,
			&serverId, &zone, &guildName, &fashionModelId, &score,
			&tempScore, &vip, &lv, &diyHeadPortraitId, &scoreChangeTime, &mapId, &star); err != nil {
			logUtil.Log(fmt.Sprintf("uncharted.GetAllPlayerInfo 从Redis中获取玩家基本信息出错3，错误信息为：%s", err), logUtil.Error, true)
			continue
		}

		// 创建对象并添加到列表中
		rankItemList = append(rankItemList, uncharted.NewRankItem(0, id, name, headImageId, pvpInterLv, serverGroupId, serverId, zone, guildName,
			fashionModelId, score+tempScore, vip, lv, diyHeadPortraitId, scoreChangeTime, mapId, star))
	}

	return
}

// 获取排名数据
// rankKey:排名key
// 返回值:
// []*uncharted.RankItem:排名后的结果
// error:错误信息
func GetRank(rankKey redisKey.RankKey) ([]*uncharted.RankItem, error) {
	conn := dal.GetRedisPool().GetConnection()
	defer conn.Close()

	// 获取排行数据
	reply, err := conn.Do("LRANGE", string(rankKey), 0, -1)
	if err != nil {
		logUtil.Log(fmt.Sprintf("从Redis中获取%s排行数据出错1，错误信息为：%s", rankKey, err), logUtil.Error, true)
		return nil, err
	}

	rankList, err := redis.Strings(reply, err)
	if err != nil {
		logUtil.Log(fmt.Sprintf("从Redis中获取%s排行数据出错2，错误信息为：%s", rankKey, err), logUtil.Error, true)
		return nil, err
	}

	rankItemList := make([]*uncharted.RankItem, 0, len(rankList))
	for _, item := range rankList {
		var rankItem *uncharted.RankItem
		if err := json.Unmarshal([]byte(item), &rankItem); err == nil {
			rankItemList = append(rankItemList, rankItem)
		}
	}

	return rankItemList, nil
}

// 保存排行榜
// rankKey:排行类型
// rankItemList:排行列表
func SaveRank(rankKey redisKey.RankKey, rankItemList []*uncharted.RankItem) {
	conn := dal.GetRedisPool().GetConnection()
	defer conn.Close()

	// 先将排行榜清空
	if _, err := conn.Do("DEL", rankKey); err != nil {
		logUtil.Log(fmt.Sprintf("从Redis中删除%s排行信息出错，错误信息为：%s", rankKey, err), logUtil.Error, true)
		return
	}

	// 如果没有排行数据则直接返回
	if len(rankItemList) == 0 {
		onlinelog.DebugLog("排行榜%s无数据，不会存储redis", rankKey)
		return
	}

	// 再将排行数据添加到列表中
	valueList := make([]interface{}, 0, len(rankItemList)+1)

	// 先将key放到列表的第一位，然后再将所有的排行数据放到后面
	valueList = append(valueList, string(rankKey))
	for _, item := range rankItemList {

		if byteSlice, err := json.Marshal(item); err != nil {
			logUtil.Log(fmt.Sprintf("序列化排行信息出错，错误信息为：%s", err), logUtil.Error, true)
			continue
		} else {
			if debugUtil.IsDebug() {
				logUtil.Log(string(byteSlice), logUtil.Warn, true)
			}

			valueList = append(valueList, string(byteSlice))
		}
	}

	// 保存到Redis中
	if _, err := conn.Do("RPUSH", valueList...); err != nil {
		logUtil.Log(fmt.Sprintf("将%s排行数据保存到Redis中出错，错误信息为：%s", rankKey, err), logUtil.Error, true)
	}
}
